﻿using Microsoft.WindowsAzure.Storage.Blob;
using PetkaWebDav.Server.Framework;
using PetkaWebDav.Server.Framework.Classes;
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading.Tasks;
using System.Web;

namespace CloudStorageLight.Core.WebDav
{
    public static class RequestWrapper
    {
        
        private static CloudBlobManager CreateCloudManager()
        {
            return new CloudBlobManager((BlobServiceBase)HttpContext.Current.Items["__BlobService__"]);
        }
       
        #region Internal Methods
        /// <summary>
        /// Retrieve's a file's lock information or loads a locked file (*.locked)
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        internal async static Task<DavLockProperty> GetLockInfoAsync(string filePath)
        {
            DavLockProperty _lockProperty = null;

            var _fileInfo = (BlobFile)await RequestWrapper.GetRequestFile();
            if (_fileInfo != null && _fileInfo.Metadata.ContainsKey("OpaqueLock"))
            {
                _lockProperty = new DavLockProperty();
                _lockProperty.AddLockToken(_fileInfo.Metadata["OpaqueLock"]);
                _lockProperty.LockOwner = _fileInfo.LockOwner;
                _lockProperty.LockOwnerType = PetkaWebDav.Server.Framework.Enums.LockOwnerType.Href;
                _lockProperty.LockType = PetkaWebDav.Server.Framework.Enums.LockType.Write;
                _lockProperty.LockScope = PetkaWebDav.Server.Framework.Enums.LockScope.Exclusive;
                
            }
            return _lockProperty;
        }


        /// <summary>
        /// Verifies the requested resource is valid
        /// </summary>
        /// <param name="urlPath">Absolute or relative URL path</param>
        /// <returns></returns>
        internal static async Task<bool> ValidResourceByPath(string urlPath)
        {
            using (var mng = CreateCloudManager())
            {
                return await mng.FileExistAsync(urlPath);
            }
        }

        /// <summary>
        /// Download Azure Blob File
        /// </summary>
        /// <param name="urlPath">File Name</param>
        /// <returns></returns>
        internal static async Task DownloadBlob(string urlPath, Stream output)
        {
            using (var mng = CreateCloudManager())
            {
                await mng.DownloadBlobAsync(urlPath, output);
            }
        }


        /// <summary>
        /// Delete Azure Blob File
        /// </summary>
        /// <param name="_filePath">Blob File Name</param>
        internal static async Task DeleteAzureFile(string _filePath)
        {
            using (var mng = CreateCloudManager())
            {
                await mng.DeleteBlobAsync(_filePath);
            }
        }

        /// <summary>
        /// Add Azure Blob File
        /// </summary>
        /// <param name="_filePath">Name for the blob</param>
        /// <param name="_stream">MemoryStream containing file</param>
        internal static async Task UploadBlob(string _filePath, MemoryStream stream)
        {
            using (var mng = CreateCloudManager())
            {
                await mng.UploadBlobAsync(stream, _filePath);
            }
        }

        ///// <summary>
        ///// Returns a lock file based on the lock token GUID
        ///// </summary>
        ///// <param name="guid"></param>
        ///// <returns></returns>
        //internal static CloudBlockBlob GetLockFileByLockToken(string guid)
        //{
        //    return _cloudManager.GetBlobLockInfoByGuid(guid);
        //}

        /// <summary>
        /// Retrieves Blobs Info
        /// </summary>
        /// <param name="fileName">Filename to retrieve attributes for</param>
        /// <returns>Null if the file does not exist</returns>
        internal static async Task<BlobItem> DownloadBlobAttributes(string fileName)
        {
            using (var mng = CreateCloudManager())
            {
                return await mng.DownloadBlobAttributes(fileName);
            }
        }

        internal static async Task<BlobItem> GetRequestFile()
        {
            using (var mng = CreateCloudManager())
            {
                var httpApplication = HttpContext.Current.ApplicationInstance;
                if (httpApplication == null)
                {
                    throw new ArgumentNullException("HttpApplication");
                }
                var path = string.Concat(httpApplication.Request.Url.Segments);
                path = AzureUtil.GetRelativeRequestPath(path);
                return await mng.DownloadBlobAttributes(path);
            }
        }

        internal static async Task CheckoutBlob(string filePath, int lockTimeout, string lockOwner, string opaqueLock = null)
        {
            using (var mng = CreateCloudManager())
            {
                await mng.CheckOutAsync(filePath, lockTimeout, lockOwner, opaqueLock);
            }
        }

        #endregion
    }
}
